home *** CD-ROM | disk | FTP | other *** search
- /*
- intrface : Browsing an Analysis Tool for C-source code;
- Interface-Module for Server and Clients,
- distinguished by defining BRS_SERVER
-
- Copyright (C) 1993 Eckehard Stolz
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation (version 2 of the License).
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <signal.h>
- #include <unistd.h>
- #include <errno.h>
- #include <sys/ipc.h>
- #include <sys/msg.h>
-
- #include "c-bat.h"
-
-
- /* On SUN's the strerror seems to be missing !
-
- Here is a substitution !
-
- (by Paul T. Keener keener@upenn5.hep.upenn.edu)
- */
- #ifdef NO_STRERROR
- /*
- * strerror for those machines that don't provide it
- */
-
- extern char *sys_errlist[];
-
- char *strerror( int errnum )
- {
-
- return sys_errlist[errnum];
-
- }
- #endif
-
-
- /*
-
- Interfacing between frontend and browser-engine is done by a
- maximaum INTRFACE_BUFFER (1KB) message.
-
- Message-Type: Server-ID (at the moment: SERVER_ID1 (c-bat.h)
-
- maximum stringsize: STRINGSIZE
-
- structure of message:
-
- Offset Type Meaning
- (Bytes)
-
- 0 short Command
-
- 2 short Additional Flags
-
- 4 int PID of Client
-
- 8 long ID of message (mainly for debugging purposes)
-
- 12 char [] Command-Arguments, separated by ","
-
-
- Commands: from frontend-module to browser-engine
- <ident> ... indentifier of function or module
- [ ] ... argument is optional
-
- Note: the ..._ONCE-commands work like the corresponding commands
- except that every symbol is just printed once !
-
- CMD_INIT Init the Browser,
- Arguments: <Browser-File>
-
- CMD_CALLS Get function-calls of a target-function
- Arguments: <target-funct> [,<target-funct-file>]
-
- CMD_CALLED_BY Get functions that call target-function
- Arguments: <target-funct> [,<target-funct-file>]
-
- CMD_FUNCT_POS Get position (file, line) of target-function
- Arguments: <target-funct> [,<target-funct-file>]
-
- CMD_VAR_POS Get position (file, line) of target-variable (global)
- Arguments: <target-var> [,<target-funct-file>]
-
- CMD_USES List usage of global variable in target-function
- Arguments: <target-funct> [,<target-funct-file>]
-
- CMD_USES_ALL List usage of all variable in target-function
- Arguments: <target-funct> [,<target-funct-file>]
-
- CMD_USED_BY List function that use target-variable
- Arguments: <target-var> [,<target-funct-file>]
-
- CMD_FILE Return Module, where FILE belongs to
- Arguments: <filename>
-
- CMD_INCLUDES Return Files, that are includes in that given file
- Arguments: <filename>
-
- CMD_FUNCTIONS Return all functions defined in the project
- Arguments: none
-
- CMD_VARIABLES Return all global (and static) variables defined in
- the project
- Arguments: none
-
- CMD_STRUCTS Return all struct defined in the project
- Arguments: none
-
- CMD_UNIONS Return all unions defined in the project
- Arguments: none
-
- CMD_ENUMS Return all enums defined in the project
- Arguments: none
-
- CMD_TYPEDEFS Return all typedefs defined in the project
- Arguments: none
-
- CMD_WHAT_IS Return (possibly more than one) type(s) of unknown <item>
- Arguments: <unknown_item> [,<file_where_item_found>]
-
- CMD_INCLUDED_BY Return files which include given file
- Arguments: <filename>
-
- CMD_REFERENCE Usage of a struct component (global/file)
- Arguments: <component_name>[,<file>]
-
- CMD_REFERENCE_F Usage of struct component in a function (no scope checking
- because we have only two arguments at the moment)
- Arguments: <component_name>,<function>
-
- CMD_REFERENCE_V Usage of component and variable in same line
- Arguments: <component_name>,<variable>
-
- CMD_FILES Return all files in project
- Arguments: none
-
- CMD_WORK_DIR Return working directory of a file
- Arguments: <file>
-
- CMD_MACRO Return all macro definitions in project
- Arguments: none
-
-
- CMD_DEF_POS Return definition position of item found at position
- file/line. File and Item is seperated by a '*'
- Arguments: <file*ident>,<line>
-
- Commands for Interfacing:
-
- CMD_CONNECT Client tries to connect to Server
- Arguments: none
-
- CMD_RELEASE Client tries to terminate connection to server
- Arguments: none
-
- CMD_TERMINATE Client wants to kill server
- Arguments: none
-
- CMD_ABORT Client aborts actual command (not implemented yet)
- Arguments: none
-
- CMD_SERVER Send request for a server-ID to the master server
- Arguments: filename of browser-file
-
- CMD_MACRO_POS Get position (file, line) of target-macro
- Arguments: <macro> [,<target-macro-file>]
-
-
- structure of return-message:
- ============================
-
- Message-Type: 32 Bit: xxxx xxxx xxxx xxxx
- cmd ----PID-------
-
- cmd: Command which caused this return 0 - 0x7f)
- PID: client-pid & 0x00ffffff
-
- Offset Type Meaning
- (Bytes)
-
- 0 short Command
-
- 2 short Additional Flags
-
- 4 int Server-ID
-
- 8 long ID of message (mainly for debugging purposes)
-
- 12 char [] Command-Arguments, separated by ","
-
-
- Return-Value: Value in command word specifies type, additional info
- in the flag word
-
- RET_FILE Return a File and (optional) Module
- Arguments: <filename> [,<modul_name>]
- Flag : 0x01 ... 1: file is part of a Module
- 0: no module defined
- Flag : 0x02 ... 1: File is system-header
- 0: File is user-header
-
- Note: if RET_FILE is a Header-file, <module_name> is
- used to return the filename of the file, where
- <filename> is included by (might be another
- headerfile in case of nested includes)
-
- RET_DIR Return a directory
- Arguments: <dirname>
-
- RET_FUNCT Return function-name and position
- Arguments: <funct>,<file>,<line> [,<module>]
- File and line can be empty, if definition position of
- function is unknown
- Flag : 0x01 ... 1: position unknown
- 0: position given
- 0x02 ... 1: module given
- 0: no module specified
- 0x04 ... 1: function is static
- 0: function is global
-
-
-
- RET_VAR Return variable-name and position
- Arguments: <var>,<file>,<line> [,<module>]
- File and line can be empty, if definition position of
- variable is unknown
- Flag : 0x01 ... 1: position unknown
- 0: position given
- 0x02 ... 1: module given
- 0: no module specified
- 0x04 ... 1: variable is static
- 0: variable is global
-
- RET_L_VAR Return local variable-name and position
- Arguments: <var>,<file>,<line>,<function>
- Flag : 0x01 ... 1: position unknown
- 0: position given
- 0x04 ... 1: variable is formal parameter
- 0: variable is local
-
- RET_POS Returns Position
- Arguments: <file>,<line> [,<module>]
- Flag : 0x01 ... 1: module given
- 0: no module specified
-
- RET_FPOS Returns Position of a function
- Arguments: <file>,<line>,<endline> [,<module>]
- Flag : 0x01 ... 1: module given
- 0: no module specified
-
- RET_STRUCT Returns struct-identifier
- Arguments: <struct>,<file>,<line>
-
- RET_UNION Returns union-identifier
- Arguments: <union>,<file>,<line>
-
- RET_ENUM Returns enum-type-identifier
- Arguments: <enum>,<file>,<line>
-
- RET_MACRO Returns macro definition
- Arguments: <macro>,<file>,<line>
-
- RET_TYPEDEF Returns typedef
- Arguments: <typedef>,<file>,<line>
-
- RET_E_CONST Returns enum-constant
- Arguments: <enum-const>,<enum>,<file>,<line>
-
- RET_S_COMP Returns component of struct
- Arguments: <component>,<struct>,<file>,<line>
-
- RET_U_COMP Returns component of union
- Arguments: <component>,<union>,<file>,<line>
-
- RET_COMP Returns component of struct or union
- Arguments: <component>,<file>,<line>
-
- RET_END No more items found
- Arguments: none
-
- RET_ERROR Specified items not found in symbol table or browser-file
- could not opened (if CMD was CMD_INIT)
- Arguments: <Error message1> [<Error message2>]
- Flag : 0x01 ... 1: error message 2 given
- 0: just error message 1
-
-
- RET_OK Command successful if CMD was CMD_INIT
- Arguments: none
-
- RET_REFERENCE File and line and function where struct component used
- Arguments: <file>,<line>,<function>
-
-
-
- Return-values for Interfacing
-
- RET_CONNECT Connection client-server established
- Server tells client application a
- recommended timeout time (in seconds)
- Arguments: <timeout>
-
- RET_REFUSED Connection client-server refused
- Arguments: String with message
-
- RET_PLEASE_WAIT Server requests more time to finish task
-
- ===================================================================
-
- Special communication between multiple servers:
-
- The first started server is the master and creates the message queue.
- Every next server - realizing that there is allready a message queue
- created - tries to request an unique ID from the master server.
-
- Master server:
- initalizes a table with all servers and their browser files.
-
- Non Master Server:
- sends the following command to the server:
-
- CMD_SERVER Hi ! I'm a new server and like to have an own ID
- Arguments: browser filename
-
- and receives following: (to the ID: TMP_SERVER_ID)
-
- Mtext[0]: new ID (instead of a return code)
- Arguments: browser filename (to check for correct recepient)
-
- If a server has to terminate and is not the master server, he tells the master
- server to free his ID by sending:
-
- [0] CMD_SERVERKILL
- [4] server ID
-
- Clients can send a request to the master server to get the ID of the server
- which processes the requested browser file
-
- CMD_SERVER_ID Return ID of the server with the following browser filename
- Arguments: browser filename
-
- The master server sends following answer:
-
- RET_ERROR ("Wrong Server" or "Unknown Browser file")
-
- RET_SERVER_ID (id returned in flags)
-
- If the master server dies and is the only one left, he removes the message queue.
- If there are other servers running, he sends the server table to an other server
- which takes over his part.
-
- In this case, he sends the
- CMD_SERVERTABLE command for each entry of the server table
- [4] server ID
-
- and
-
- CMD_S_TABLE_END at the end of the table. In this case, the new server has to send
- an acknowledgement by resending this message
- [4] server ID
- */
-
-
-
-
- #define INTRFACE_BUFSIZE 1024
-
-
- struct msgform {
- long mtype;
- char mtext[INTRFACE_BUFSIZE];
- };
-
- static struct msgform Msg; /* message buffer */
-
- static key_t key = DEFAULT_KEY;
- static int msqid;
-
-
- static short first = 1;
-
-
- #ifdef BRS_SERVER
-
- /* init function for server
- */
- extern void terminate_handler(int sig);
-
- /* Tries to create IPC ressource. if one exists, it returns 0 idicating that
- there is a ressource still left or that there is allready a master server
- running. If the value of 1 is returned, this server is the master server !
- */
- static int init_interface(void)
- {
- first = 0;
-
- if ((msqid = msgget (key, 0777 | IPC_CREAT | IPC_EXCL)) == -1) {
- switch( errno )
- { case EEXIST: /* message queue does allready exist. Try to
- connect to master */
- if ((msqid = msgget (key, 0777 )) == -1) {
- fprintf(stderr, "Init-Interface: msgget: errno: %d (%s)\n",
- errno, strerror(errno) );
- exit( 1 );
- }
- return(0);
- break;
-
- default:
- fprintf(stderr, "Init-Interface: msgget: errno: %d (%s)\n",
- errno, strerror(errno) );
- exit( 1 );
- break;
- }
- }
- return( 1 );
- }
-
- #else
-
- /* Init function for client
- return value is "don't care"
- */
- static int init_interface(void)
- {
- first = 0;
-
- if ((msqid = msgget (key, 0777 )) == -1) {
- fprintf(stderr, "Init-Interface: msgget: errno: %d (%s)\n",
- errno, strerror(errno) );
- exit( 1 );
- }
- return(0);
-
- }
- #endif
-
- /* Debug-function: returns any message from message-queue
- */
- short brs_get_any_message(int *type, short *cmd, short *flag, int *pid, long *id, char *buf)
- { int cnt;
-
- cnt = msgrcv( msqid, (struct msgbuf *) &Msg,
- INTRFACE_BUFSIZE, 0, IPC_NOWAIT);
-
- if( cnt == -1 )
- return(cnt);
-
- *cmd = *((short *) Msg.mtext );
- *flag = *((short *) (Msg.mtext + 2) );
- *pid = *((int *) (Msg.mtext + 4) );
- *id = *((long *) (Msg.mtext + 8) );
-
- *type = Msg.mtype;
-
- strncpy( buf, Msg.mtext + ARGUMENT_OFFSET, INTRFACE_BUFSIZE - 8 );
- return( cnt );
- }
-
-
- /*********************************************************************
- **********************************************************************
-
- THIS PART OF THE CODE ARE THE MAIN INTERFACING ROUTINES FOR THE SERVER
-
- **********************************************************************
- *********************************************************************/
-
- #ifdef BRS_SERVER
-
- /* struct for server-table. Every running server has a table which
- holds the id's and the name of the browser file
- */
- struct server_table
- { int server_id;
- char *filename;
- };
-
- short cnt_servers = MASTER_ID;
-
- struct server_table s_table[MAX_SERVERS + MASTER_ID];
-
- long cmd_id = 0;
- long ret_id = 0;
-
- static int cmd_msg_flag; /* command used for selective message return */
-
- /* time needed for initial scanning. Used to tell
- clients minimum timeout-time
- */
- extern time_t lex_time;
-
- int client_pid; /* PID of client, that issued actual command */
-
- static int server_id = MASTER_ID, /* ID of this server */
- alias_id = 0; /* Might be Master-ID */
-
- /* Pointer to the browser-filename of this server
- */
- static char *browser_filename = NULL;
-
- /* This array should be extended to the following values:
-
- short issued_cmd; command last issued
- short state; PENDING, WORKING, COMPLETED
- time_t last; time of last message sent
-
- This information should be used for the be_patient-function,
- which informs the clients that the server needs more time to
- finish their requests
- */
- static client_pid_array[MAX_CLIENTS];
- static short cnt_clients = 0;
-
- /* Sends a message to the message queue. If EAGAIN, it waits for 0.1 sec and
- tries to resend the message until the TIMEOUT elapsed
- */
- short send_msg( int cnt, int pos )
- { long elapsed_time = 0;
-
- while( 1 )
- { if( msgsnd( msqid, (struct msgbuf *) &Msg, cnt, IPC_NOWAIT ) == -1 )
- { if( errno != EAGAIN )
- { fprintf(stderr, "SERVER: (PID: %d, Pos %d) msgsnd failed: errno: %d (%s)\n",
- getpid(), pos, errno, strerror(errno) );
- exit( 1 );
- }
- else
- { /* EAGAIN, wait for 0.1 sec and then try again */
- usleep( 100000 );
- elapsed_time += 100;
- if( elapsed_time >= ( SECONDS_TIMEOUT * 1000) )
- { /* Timeout ! Ignore this message
- */
- fprintf(stderr, "SERVER: (PID: %d, Pos: %d) Warning: message ignored !\n",
- getpid(), pos );
- return( 1 );
- }
- }
- }
- else
- return( 0 );
- }
- }
-
-
- /* Used to set the actual name of the browser file in the
- internal data structures (and the one of the master server)
- */
- void set_browser_filename(char *filename)
- { short cmd;
- int cnt;
-
- browser_filename = filename;
-
- if( server_id != MASTER_ID && alias_id != MASTER_ID )
- { /* send new browser-file to the master-server
- */
- Msg.mtype = MASTER_ID;
- cmd = CMD_NEW_FILE;
-
- memcpy( Msg.mtext , &cmd , sizeof(short) );
- memcpy( Msg.mtext + 4, &server_id, sizeof(short) );
-
- ret_id++;
- memcpy( Msg.mtext + 8, &ret_id, sizeof(short) );
-
- strcpy( Msg.mtext + ARGUMENT_OFFSET, browser_filename );
-
- cnt = ARGUMENT_OFFSET + strlen( Msg.mtext + ARGUMENT_OFFSET ) + 1;
-
- send_msg( cnt, 1 );
- }
- else
- { /* this server is the master, just update the server-table */
- if( s_table[server_id].filename )
- free( s_table[server_id].filename );
-
- s_table[server_id].filename = strdup( browser_filename );
- }
- }
-
- /* This function sends the server-id to the master-server
- telling that this id will not be used anymore
- called by the termination handler
- */
- void free_server_id(void)
- { short cmd;
- short tmp;
- short i;
- int cnt;
- long elapsed_time = 0;
-
- if( server_id == MASTER_ID || alias_id == MASTER_ID )
- { /* Killing of the master-server. If it is the only
- running server, free message queue, otherwise,
- tell other server to become master
- */
- for( i = MASTER_ID; i < cnt_servers; i++ )
- { if( s_table[i].server_id != 0 &&
- s_table[i].server_id != server_id )
- break;
- }
- if( i == cnt_servers )
- { /* This server is the only one left, now we can delete the ressource
- */
- if( msgctl( msqid, IPC_RMID, 0 ) == -1 )
- { fprintf(stderr, "SERVER: (PID: %d, Pos: 2)Remove MSQ: errno: %d (%s)\n",
- getpid(), errno, strerror(errno) );
- exit( 1 );
- }
- return;
- }
- else
- { /* Master server has to be killed, but there are other servers running.
- choose server i to take the master server part
- */
-
- Msg.mtype = i;
- cmd = CMD_SERVERTABLE;
-
- memcpy( Msg.mtext, &cmd, sizeof(short) );
- memcpy( Msg.mtext + 4, &server_id, sizeof(short) );
-
- for( i = MASTER_ID; i < cnt_servers; i++ )
- { if( s_table[i].server_id &&
- s_table[i].server_id == server_id )
- { /* do not send own entry, a deleted entry instead */
- tmp = 0;
- memcpy( Msg.mtext + 2 , &tmp, sizeof(short) );
- strcpy( Msg.mtext + ARGUMENT_OFFSET, "" );
- }
- else
- { memcpy( Msg.mtext + 2 , &(s_table[i].server_id), sizeof(short) );
- if( s_table[i].filename )
- strcpy( Msg.mtext + ARGUMENT_OFFSET, s_table[i].filename );
- else
- strcpy( Msg.mtext + ARGUMENT_OFFSET, "" );
- }
-
- cnt = strlen(s_table[i].filename) + 1 + ARGUMENT_OFFSET;
-
- ret_id++;
- memcpy( Msg.mtext + 8, &ret_id, sizeof(short) );
-
- send_msg( cnt, 3 );
- }
-
- /* tell new master that the table has been sent completly
- */
- ret_id++;
- memcpy( Msg.mtext + 8, &ret_id, sizeof(short) );
-
- cmd = CMD_S_TABLE_END;
- memcpy( Msg.mtext, &cmd, sizeof(short) );
- send_msg( cnt, 4 );
-
- /* Now we just have to wait for the acknoledgment of the new master
- After this O.K., we are allowed to die !
- */
- while(1)
- { cnt = msgrcv( msqid, (struct msgbuf *) &Msg,
- INTRFACE_BUFSIZE, MASTER_ID, IPC_NOWAIT);
- if( cnt < 0 && errno != ENOMSG )
- { fprintf(stderr, "SERVER: (PID: %d, Pos 5) msgrcv: errno: %d (%s)\n",
- getpid(), errno, strerror(errno) );
- exit( 1 );
- }
- if( cnt > 0 )
- { cmd = *((short *)Msg.mtext);
- if( cmd != CMD_S_TABLE_END )
- { /* wrong command, send back
- */
- send_msg( cnt, 6 );
- }
- else
- { /* New Master sent acknowledgement
- o.k., we can die now !
- */
- return;
- }
- }
- usleep( 100000 );
- elapsed_time += 100;
- if( elapsed_time >= (3 * SECONDS_TIMEOUT * 1000) )
- { /* Timeout ! No Acknowledgment received
- */
- fprintf(stderr, "Old Master Server: New Master does not respond !\n");
- fprintf(stderr, "You should kill all browser programs and delete the message queue\n");
- fprintf(stderr, "using the ipcrm-command ! \n");
- fprintf(stderr, "A complete restart is HIGHLY recommended ! \n");
- return;
- }
- } /* endwhile */
- }
- }
- else
- { /* Killing of a non master server. Just tell the
- server to free it's server id
- */
- Msg.mtype = MASTER_ID;
- cmd = CMD_SERVERKILL;
-
- memcpy( Msg.mtext, &cmd, sizeof(short) );
- memcpy( Msg.mtext + 4 , &server_id, sizeof(short) );
- ret_id++;
- memcpy( Msg.mtext + 8, &ret_id, sizeof(short) );
-
- send_msg( cnt, 7 );
- }
- }
-
-
- /* This is the main initializing routine for the servers. If a message-queue
- was already created (detected by init_interface), this routine tries to
- connect to the server. On succes, it set's the server_id to the one re-
- ceived by the master server
- */
- int init_server(void)
- { static short first = 1;
- short cmd, i;
- int cnt;
- long elapsed_time = 0;
-
- if( !first )
- return(0);
-
- first = 0;
- if( init_interface() )
- { /* This server is the master. Initialize
- master-data-structures
- */
- for( i = 0; i < MAX_SERVERS + MASTER_ID; i++ )
- { s_table[i].filename = NULL;
- s_table[i].server_id = 0;
- }
- cnt_servers = MASTER_ID;
- s_table[cnt_servers].server_id = MASTER_ID;
- s_table[cnt_servers].filename = strdup( browser_filename );
- if( !(s_table[cnt_servers].filename) )
- { fprintf(stderr, "SERVER: (PID: %d, Pos 9): Not enough memory for strdup\n",
- getpid() );
- exit( 1 );
- }
-
- cnt_servers++;
- }
- else
- { /* This server is NOT the master. Send the browser-filename
- to the server
- */
- Msg.mtype = MASTER_ID;
- cmd = CMD_SERVER;
-
- i = -1;
- memcpy( Msg.mtext, &cmd, sizeof(short) );
- memcpy( Msg.mtext + 4, &i, sizeof(short) );
-
- ret_id++;
- memcpy( Msg.mtext + 8, &ret_id, sizeof(int) );
- strcpy( Msg.mtext + ARGUMENT_OFFSET, browser_filename );
-
- cnt = ARGUMENT_OFFSET + strlen( Msg.mtext + ARGUMENT_OFFSET ) + 1;
-
- send_msg( cnt, 10 );
-
- /* Now wait for the assigned Server-ID
- */
- while(1)
- { cnt = msgrcv( msqid, (struct msgbuf *) &Msg,
- INTRFACE_BUFSIZE, TMP_SERVER_ID, IPC_NOWAIT);
- if( cnt < 0 && errno != ENOMSG )
- { fprintf(stderr, "SERVER: (PID: %d, Pos 11) msgrcv: errno: %d (%s)\n",
- getpid(), errno, strerror(errno) );
- exit( 1 );
- }
- if( cnt > 0 )
- { if( !strcmp( Msg.mtext + ARGUMENT_OFFSET, browser_filename ) )
- { /* the right (same browser-file) message received
- */
- server_id = *((short *) Msg.mtext);
- break;
- }
- else
- { /* wrong message: send back
- */
- send_msg( cnt, 12 );
- } /* endelse */
- }
- usleep( 100000 );
- elapsed_time += 100;
- if( elapsed_time >= ( 2 * SECONDS_TIMEOUT * 1000) )
- { /* Timeout ! Cannot connect to server
- */
- fprintf(stderr, "Server: Cannot connect to master server !\n");
- fprintf(stderr, "Maybe there is a message queue left. If there is no other server running,\n");
- fprintf(stderr, "please remove message queue using the ipcrm-command ! \n");
- exit( 1 );
- }
- } /* endwhile */
- } /* endelse not master */
-
- /* define signal handling if server has to terminate
- This handler just removes the ipc-message queue
- */
- signal( SIGINT, terminate_handler);
- signal( SIGTERM, terminate_handler);
- signal( SIGHUP, terminate_handler);
- signal (SIGKILL, terminate_handler);
- signal (SIGQUIT, terminate_handler);
-
- }
-
-
- static short Is_client( int pid )
- { short i;
-
- for( i = 0; i < cnt_clients; i++ )
- { if( client_pid_array[i] == pid )
- break;
- }
-
- if( i == cnt_clients )
- return( 0 ); /* PID not found: no client ! */
- else
- return( i + 1 ); /* TRUE: pid found */
- }
-
-
- /* Wait till a command is sent by a frontend-module. Get this command
- and its arguments
- */
- short get_brs_cmd(char *arg1, char *arg2)
- { short cmd, i;
- char *p1, *p2;
- char ret_arg1[STRINGSIZE];
- static short s_table_received = 0;
-
- int pid,
- server,
- cnt;
-
- if( first )
- init_server();
-
- top: /* if a connect or release-command issued, wait for net message*/
-
- /* get message from message queue: msgflg is set to 0, so this call waits
- untill there's a message or the server receives a signal
- */
- server = server_id;
- while( 1 )
- { cnt = msgrcv( msqid, (struct msgbuf *) &Msg,
- INTRFACE_BUFSIZE, server, IPC_NOWAIT);
- if( cnt < 0 && errno != ENOMSG )
- { fprintf(stderr, "SERVER: (PID: %d, Pos 14) msgrcv: errno: %d (%s)\n",
- getpid(), errno, strerror(errno) );
- exit( 1 );
- }
- if( cnt >= 0 )
- break;
- server = ( (server == server_id) && alias_id) ? alias_id : server_id ;
- usleep( 100000 );
- }
-
- cmd = *((short *) Msg.mtext);
- pid = *((int *)(Msg.mtext + 4));
- cmd_id = *((int *)(Msg.mtext + 8));
-
- switch( cmd )
- { case CMD_CONNECT: /* commands issued by a server, not a client */
- case CMD_SERVER:
- case CMD_SERVERKILL:
- case CMD_SERVERTABLE:
- case CMD_S_TABLE_END:
- case CMD_NEW_FILE: break;
-
- case CMD_SERVER_ID: /* command may be issued by any client */
- break;
-
-
- default: if( pid && !Is_client( pid ) )
- { /* Client not known: ignore message ! */
- fprintf(stderr, "Server (PID %d) Warning: Unknown Client (pid ? %d)\n",
- getpid(), pid);
- goto top;
- }
- }
-
- cmd_msg_flag = cmd & 0x7f;
-
- p1 = NULL;
- p2 = NULL;
-
- switch(cmd)
- { /* Commands, which have no arguments:
- */
- case CMD_FUNCTIONS: /* Return all functions defined in the project */
- /* Arguments: none */
- case CMD_VARIABLES: /* Return all global (and static) variables */
- /* defined in the project */
- /* Arguments: none */
- case CMD_ENUMS: /* Return all enums, structs, unions and */
- case CMD_STRUCTS: /* typedefs */
- case CMD_UNIONS:
- case CMD_TYPEDEFS:
- case CMD_FILES:
- case CMD_MACROS:
- break;
-
- /* Commands, which have one argument:
- */
- case CMD_INIT: /* Init the Browser, Arguments: <Browser-File> */
- case CMD_FILE: /* Return Module, where FILE belongs to */
- /* Args: <filename> */
- case CMD_INCLUDES: /* Return Files, that are includes in that */
- /* given file */
- /* Args: <filename> */
- case CMD_REFERENCE:
- case CMD_WORK_DIR: /* Working directory of a file in the project */
- /* Args: <filename> */
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- break;
-
- /* Commands, which have two arguments:
- */
- case CMD_CALLS: /* Get function-calls of a target-function */
- /* Args: <target-funct> [,<target-funct-file>] */
- case CMD_CALLED_BY: /* Get functions that call target-function */
- /* Args: <target-funct> [,<target-funct-file>] */
- case CMD_CALLS_ONCE:
- case CMD_CALLED_BY_ONCE:
- /* Args: <target-funct> [,<target-funct-file>] */
- case CMD_FUNCT_POS: /* Get position (file, line) of target-function */
- /* Args: <target-funct> [,<target-funct-file>] */
- case CMD_VAR_POS: /* Get position (file, line) of target-variable */
- /* Args: <target-var> [,<target-funct-file>] */
- case CMD_MACRO_POS: /* Get position (file, line) of target-macro */
- /* Args: <target-macro> [,<target-macro-file>] */
- case CMD_USES: /* List usage of global variable in target */
- /* Args: <target-funct> [,<target-funct-file>] */
- case CMD_USES_ALL: /* List usage of all vars in target-function */
- /* Args: <target-funct> [,<target-funct-file>] */
- case CMD_USED_BY: /* List function that use target-variable */
- /* Args: <target-var> [,<target-funct-file>] */
- case CMD_DEF_POS:
- case CMD_USES_ONCE:
- case CMD_USED_BY_ONCE:
- case CMD_REFERENCE_F:
- case CMD_REFERENCE_V:
- case CMD_WHAT_IS:
-
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- p2 = strtok( NULL, "," );
- break;
-
- case CMD_CONNECT: /* Client requests connection to server */
-
- if( cnt_clients == MAX_CLIENTS )
- { /* send refused */
- send_brs_ret( RET_REFUSED, 0, pid,
- "Too many clients", "", "", "" );
- }
- else
- { /* connection established, add pid to table, if
- not allready in there
- */
- sprintf(ret_arg1,"%ld", (long)lex_time * 2);
- if( !Is_client( pid ) )
- { client_pid_array[cnt_clients++] = pid;
- send_brs_ret( RET_CONNECT, 0, pid, ret_arg1, "", "", "" );
- }
- else
- { /* allready connected */
- send_brs_ret( RET_CONNECT, 1, pid, ret_arg1, "", "", "" );
- }
- }
-
- goto top;
-
- case CMD_TABLE: /* send server-table to client */
-
- for( i = MASTER_ID; i < cnt_servers; i++ )
- { send_brs_ret( RET_FILE, s_table[i].server_id, pid,
- (s_table[i].filename) ? s_table[i].filename : "", "", "", "" );
- }
- send_brs_ret( RET_END, 0, pid, "", "", "", "" );
-
- goto top;
-
- case CMD_RELEASE:
-
- if( cnt_clients == 0 )
- { /* send refused */
- send_brs_ret( RET_REFUSED, 0, pid,
- "No Client", "", "", "" );
- }
- else
- { for( i = 0; i < cnt_clients; i++ )
- { if( client_pid_array[i] == pid )
- break;
- }
-
- if( i == cnt_clients )
- { send_brs_ret( RET_REFUSED, 0, pid,
- "No Client", "", "", "" );
- }
- else
- { client_pid_array[i] = client_pid_array[cnt_clients-1];
- cnt_clients--;
- }
- }
-
- goto top;
-
- case CMD_TERMINATE: /* Kill server */
-
- if( s_table_received )
- { /* the master server is sending the new server table.
- while this is going on, ignore the request for
- termination and push it back to the queue for later
- processing
- */
- send_msg( cnt, 16 );
-
- goto top;
- }
-
- free_server_id();
- fprintf(stderr, "SERVER: (PID: %d) Terminate as requested\n",
- getpid() );
- exit( 0 );
-
- case CMD_ABORT: break; /* currently unimplemented */
-
- case CMD_SERVER: /* a server requests a server-id */
-
- /* find free server-id
- */
- for( i = MASTER_ID + 1; i < cnt_servers; i++ )
- { if( s_table[i].server_id == 0 )
- break;
- }
-
- /* create server entry
- */
- s_table[i].server_id = i;
- s_table[i].filename = strdup( Msg.mtext + ARGUMENT_OFFSET );
- if( !(s_table[i].filename) )
- { fprintf(stderr, "SERVER: (PID: %d, Pos 15): Not enough memory for strdup\n",
- getpid() );
- exit( 1 );
- }
- if( i == cnt_servers )
- cnt_servers++;
-
- /* send the new server id to this server
- */
- Msg.mtype = TMP_SERVER_ID;
- memcpy( Msg.mtext, &i, sizeof(short) );
- memcpy( Msg.mtext + 4, &server_id, sizeof(short) );
- ret_id++;
- memcpy( Msg.mtext + 8, &ret_id, sizeof(int) );
-
- send_msg( cnt, 17 );
-
- goto top;
-
- case CMD_SERVERKILL: /* a server is freeing his server-id */
-
- /* find this server-id
- */
- for( i = MASTER_ID; i < cnt_servers; i++ )
- { if( s_table[i].server_id == pid )
- break;
- }
- if( i == cnt_servers )
- { fprintf(stderr, "SERVER: (PID: %d) Unknown Server (%hd) requests killing\n",
- getpid(), pid );
- break;
- }
- s_table[i].server_id = 0;
- free( s_table[i].filename );
- s_table[i].filename = NULL;
-
- goto top;
-
- case CMD_SERVER_ID: /* a client want's to know a server id */
-
- if( server != MASTER_ID )
- { /* This request can only be sent to a master
- */
- send_brs_ret( RET_ERROR, 0, pid, "Wrong server", "", "", "" );
- break;
- }
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
-
- /* find matching browser file
- */
- for( i = 0; i < cnt_servers; i++ )
- { if( s_table[i].server_id && !strcmp( s_table[i].filename, p1) )
- break;
- }
-
- if( i == cnt_servers )
- { /* server with specified browserfile not found
- send error message
- */
- send_brs_ret( RET_ERROR, 0, pid, "Unknown browser file", "", "", "" );
- break;
- }
-
- send_brs_ret( RET_SERVER_ID, s_table[i].server_id, pid, "", "", "", "" );
-
- goto top;
-
- case CMD_SERVERTABLE: /* old master sends its server table */
-
- s_table[cnt_servers].server_id = *((short *)(Msg.mtext + 2));
- if( s_table[cnt_servers].server_id )
- s_table[cnt_servers].filename = strdup( Msg.mtext + ARGUMENT_OFFSET);
- else
- s_table[cnt_servers].filename = NULL;
-
- cnt_servers++;
- s_table_received = 1;
-
- goto top;
-
- case CMD_S_TABLE_END: /* server-table is now complete: send acknowledgment */
- if( s_table_received )
- { /* we got this command right after the server-table, send
- acknoledgment now
- */
- s_table_received = 0;
- Msg.mtype = MASTER_ID;
- ret_id++;
- memcpy( Msg.mtext + 4, &server_id, sizeof(int) );
- memcpy( Msg.mtext + 8, &ret_id, sizeof(int) );
- send_msg( cnt, 18 );
-
- /* This server is now the master
- */
- alias_id = MASTER_ID;
- }
- else
- { /* we got this message accidentially, it is intented for
- the old master. Send it back !
- */
- send_msg( cnt, 19 );
- }
-
- usleep( 100000 );
-
- goto top;
-
-
- case CMD_NEW_FILE:
- i = *((short *) Msg.mtext + 4);
-
- if( s_table[i].filename )
- free( s_table[i].filename );
- s_table[i].filename = strdup( Msg.mtext + ARGUMENT_OFFSET );
- if( !(s_table[i].filename) )
- { fprintf(stderr, "SERVER: (PID: %d, Pos 19): Not enough memory for strdup\n",
- getpid() );
- exit( 1 );
- }
-
- goto top;
-
- default:
- send_brs_ret( RET_CMD_UNKNOWN, cmd, pid, "", "", "", "" );
- goto top;
- break;
- }
-
- arg1[0] = 0;
- arg2[0] = 0;
-
- if( p1 )
- { if( strlen( p1 ) > STRINGSIZE )
- { strncpy( arg1, p1, STRINGSIZE-1 );
- arg1[STRINGSIZE-1] = 0;
- }
- else
- strcpy( arg1, p1 );
- }
- else
- strcpy( arg1, "" );
-
- if( p2 )
- { if( strlen( p2 ) > STRINGSIZE )
- { strncpy( arg2, p2, STRINGSIZE-1 );
- arg2[STRINGSIZE-1] = 0;
- }
- else
- strcpy( arg2, p2 );
- }
- else
- strcpy( arg2, "" );
-
- client_pid = pid;
-
- return( cmd );
- }
-
-
- /* Returns the result of the request to the client process
- */
- void send_brs_ret( short ret_code, short flag, int pid,
- char * arg1, char *arg2, char *arg3, char *arg4 )
- { short cmd;
- short cnt;
-
- if( first )
- init_interface();
-
- Msg.mtype = (pid & 0x00ffffff) | ((int)(cmd_msg_flag & 0x7f) << 24);
- ret_id++;
-
- memcpy( Msg.mtext, &ret_code, sizeof(short) );
- memcpy( Msg.mtext + 2, &flag, sizeof(short) );
- memcpy( Msg.mtext + 4, &server_id, sizeof(int) );
- memcpy( Msg.mtext + 8, &ret_id, sizeof(int) );
-
- /* Test, if buffer is able to hold date:
- length of strings + 3 Bytes ',' + 1 Byte '\0' + ARGUMENT_OFFSET
- */
- cnt = strlen(arg1) + strlen(arg2) + strlen(arg3) +
- strlen(arg4) + 4 + ARGUMENT_OFFSET;
-
- if( cnt > INTRFACE_BUFSIZE )
- { fprintf( stderr, "Data to transfer exceeds buffersize !\n" );
- exit(1);
- }
-
- /* Copy arguments to buffer, separated by ','
- */
- if( arg4[0] )
- sprintf( Msg.mtext + ARGUMENT_OFFSET, "%s,%s,%s,%s",
- arg1, arg2, arg3, arg4 );
- else if( arg3[0] )
- sprintf( Msg.mtext + ARGUMENT_OFFSET, "%s,%s,%s" ,
- arg1, arg2, arg3 );
- else if( arg2[0] )
- sprintf( Msg.mtext + ARGUMENT_OFFSET, "%s,%s" ,
- arg1, arg2 );
- else if( arg1[0] )
- sprintf( Msg.mtext + ARGUMENT_OFFSET, "%s" ,
- arg1 );
- else
- strcpy( Msg.mtext + ARGUMENT_OFFSET, "" );
-
- cnt = ARGUMENT_OFFSET + strlen( Msg.mtext + ARGUMENT_OFFSET ) + 1;
-
- send_msg( cnt, 20 );
- }
-
-
- /* Handler for SIGINT and SIGTERM
-
- Just remove the IPC-message queue
-
- */
- void terminate_handler(int sig)
- {
- free_server_id();
- fprintf(stderr, "SERVER: (PID: %d): Interrupted\n", getpid() );
- exit( 0 );
- }
-
-
- /*********************************************************************
- **********************************************************************
-
- THIS PART OF THE CODE ARE THE MAIN INTERFACING ROUTINES FOR THE CLIENT
-
- **********************************************************************
- *********************************************************************/
-
- #else /* BRS_CLIENT */
-
- long cmd_id = 0;
- long ret_id = 0;
-
- int timeout_value = SECONDS_TIMEOUT;
-
- /* Sends a message to the message queue. If EAGAIN, it waits for 0.1 sec and
- tries to resend the message until the TIMEOUT elapsed
- THIS IS THE CLIENT VERSION
- */
- short send_msg( int cnt, int pos )
- { long elapsed_time = 0;
-
- while( 1 )
- { if( msgsnd( msqid, (struct msgbuf *) &Msg, cnt, IPC_NOWAIT ) == -1 )
- { if( errno != EAGAIN )
- { fprintf(stderr, "CLIENT: (PID: %d, Pos %d) msgsnd failed: errno: %d (%s)\n",
- getpid(), pos, errno, strerror(errno) );
- exit( 1 );
- }
- else
- { /* EAGAIN, wait for 0.1 sec and then try again */
- usleep( 100000 );
- elapsed_time += 100;
- if( elapsed_time >= ( SECONDS_TIMEOUT * 1000) )
- { /* Timeout ! Ignore this message
- */
- fprintf(stderr, "CLIENT: (PID: %d, Pos: %d) Warning: message ignored !\n",
- getpid(), pos );
- return( 1 );
- }
- }
- }
- else
- return( 0 );
- }
- }
-
- /* Wait till a return is sent by server. Get return-code
- the flag (if r_flag != NULL) and arguments
- */
- short get_brs_ret(short command, int * server, short *r_flag,
- char *arg1, char *arg2, char *arg3, char *arg4)
- { short cmd, flag;
- char *p1, *p2, *p3, *p4;
- int pid,
- msg_type,
- server_id,
- cnt;
- long elapsed_time = 0; /* in milliseconds */
-
- if( first )
- init_interface();
-
- pid = getpid();
-
- msg_type = (pid & 0xffffff) | ((int)(command & 0x7f) << 24);
-
- /* get message from message queue: try to get the message
- */
- while( 1 )
- { cnt = msgrcv( msqid, (struct msgbuf *) &Msg,
- INTRFACE_BUFSIZE, msg_type, IPC_NOWAIT);
- if( cnt == -1 )
- { /* message not found wait for 100.000 micro-seconds
- equals 0.1 seconds
- */
- usleep( 100000 );
- elapsed_time += 100;
- if( elapsed_time >= (timeout_value * 1000) )
- return( RET_TIMEOUT );
- }
- else
- break;
- }
-
-
- cmd = *((short *) Msg.mtext );
-
- /* here goes the test if the Server sent the be_patient-return.
-
- if so, call the (possibly) user defined function and
- abort this command if this functions returns nonzero
-
- - currently unimplemented
-
- if( cmd == RET_PLEACE_WAIT )
- { erg = (*be_patient_user)();
- if( erg )
- { sent_brs_cmd( CMD_ABORT, ...)
- return
- }
- elapsed_time = 0;
- goto while_
- }
- */
- flag = *((short *) (Msg.mtext + 2) );
- server_id = *((int *) (Msg.mtext + 4) );
- ret_id = *((int *) (Msg.mtext + 8) );
-
- if( r_flag )
- *r_flag = flag;
-
- /* printf("cmd: %hd, flag %hx, server-id: %ld\n", cmd, flag, server_id ); */
-
-
- p1 = NULL;
- p2 = NULL;
- p3 = NULL;
- p4 = NULL;
-
- switch(cmd)
- { case RET_FILE:
- case RET_ERROR:
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- if( flag & 0x01 )
- /* module given */
- p2 = strtok( NULL, "," );
- break;
-
- case RET_FUNCT:
- case RET_VAR:
- case RET_L_VAR:
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- if( !(flag & 0x01) )
- { /* position is given
- */
- p2 = strtok( NULL, "," );
- p3 = strtok( NULL, "," );
- if( !(flag & 0x02) )
- /* module given */
- p4 = strtok( NULL, "," );
- }
- break;
-
- case RET_STRUCT:
- case RET_UNION:
- case RET_ENUM:
- case RET_TYPEDEF:
- case RET_MACRO:
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- if( !(flag & 0x01) )
- { /* position is given
- */
- p2 = strtok( NULL, "," );
- p3 = strtok( NULL, "," );
- /* module ignored */
- }
- break;
-
- case RET_REFERENCE:
- case RET_COMP:
- case RET_ENUM_C:
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- p2 = strtok( NULL, "," );
- p3 = strtok( NULL, "," );
- break;
-
- case RET_POS:
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- p2 = strtok( NULL, "," );
- if( flag & 0x01 )
- { /* module is given
- */
- p3 = strtok( NULL, "," );
- }
- break;
-
- case RET_FPOS:
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- p2 = strtok( NULL, "," );
- p3 = strtok( NULL, "," );
- if( flag & 0x01 )
- { /* module is given
- */
- p4 = strtok( NULL, "," );
- }
- break;
-
- case RET_CONNECT: /* should also send a version-string to client */
- /* currently not implemented */
- case RET_REFUSED:
- case RET_DIR: /* working directory - just 1 argument */
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- break;
-
- case RET_END:
- case RET_OK:
- case RET_CMD_UNKNOWN:
- case RET_PLEASE_WAIT: /* currently not implemented */
- break;
-
- default:
- return( cmd ); /* unknown command */
- break;
- }
-
- arg1[0] = 0;
- arg2[0] = 0;
- arg3[0] = 0;
- arg4[0] = 0;
-
- if( p1 )
- { if( strlen( p1 ) > STRINGSIZE )
- { strncpy( arg1, p1, STRINGSIZE-1 );
- arg1[STRINGSIZE-1] = 0;
- }
- else
- strcpy( arg1, p1 );
- }
- else
- strcpy( arg1, "" );
-
- if( p2 )
- { if( strlen( p2 ) > STRINGSIZE )
- { strncpy( arg2, p2, STRINGSIZE-1 );
- arg2[STRINGSIZE-1] = 0;
- }
- else
- strcpy( arg2, p2 );
- }
- else
- strcpy( arg2, "" );
-
- if( p3 )
- { if( strlen( p3 ) > STRINGSIZE )
- { strncpy( arg3, p3, STRINGSIZE-1 );
- arg3[STRINGSIZE-1] = 0;
- }
- else
- strcpy( arg3, p3 );
- }
- else
- strcpy( arg3, "" );
-
- if( p4 )
- { if( strlen( p4 ) > STRINGSIZE )
- { strncpy( arg4, p4, STRINGSIZE-1 );
- arg2[STRINGSIZE-1] = 0;
- }
- else
- strcpy( arg4, p4 );
- }
- else
- strcpy( arg4, "" );
-
- return( cmd );
- }
-
-
-
- void send_brs_cmd( int server, short ret_code, short flag, char * arg1, char *arg2)
- { short cmd;
- short cnt;
- int pid;
-
- if( first )
- init_interface();
-
- pid = getpid();
-
- /* message goes to server :
- */
- Msg.mtype = server;
-
- cmd_id++;
-
- memcpy( Msg.mtext, &ret_code, sizeof(short) );
- memcpy( Msg.mtext + 2, &flag, sizeof(short) );
- memcpy( Msg.mtext + 4, &pid , sizeof(int) );
- memcpy( Msg.mtext + 8, &cmd_id, sizeof(int) );
-
- /* Test, if buffer is able to hold date:
- length of strings + 1 Byte ',' + 1 Byte '\0' + ARGUMENT_OFFSET
- */
- cnt = strlen(arg1) + strlen(arg2) + 2 + ARGUMENT_OFFSET;
-
- if( cnt > INTRFACE_BUFSIZE )
- { fprintf( stderr, "Data to transfer exceeds buffersize !\n" );
- exit(1);
- }
-
- /* Copy arguments to buffer, separated by ','
- */
- if( arg2[0] )
- sprintf( Msg.mtext + ARGUMENT_OFFSET, "%s,%s" , arg1, arg2 );
- else if( arg1[0] )
- sprintf( Msg.mtext + ARGUMENT_OFFSET, "%s" , arg1 );
- else
- strcpy( Msg.mtext + ARGUMENT_OFFSET, "" );
-
- cnt = ARGUMENT_OFFSET + strlen( Msg.mtext + ARGUMENT_OFFSET ) + 1;
-
- send_msg( cnt, 0 );
- }
-
-
- /* get messages in queue
- */
- short brs_get_msg_debug(short command, int * server, int *pid, short *ret_cmd, int *ret_id,
- short *r_flag, char *arg1,
- char *arg2, char *arg3, char *arg4)
- { short cmd, flag;
- char *p1, *p2, *p3, *p4;
- int server_id,
- msg_type,
- cnt;
- long elapsed_time = 0; /* in milliseconds */
-
- if( first )
- init_interface();
-
- if( command == 0 )
- msg_type = 0;
- else
- msg_type = (*pid & 0xffffff) | ((int)(command & 0x7f) << 24);
-
- /* get message from message queue: try to get the message
- */
- while( 1 )
- { cnt = msgrcv( msqid, (struct msgbuf *) &Msg,
- INTRFACE_BUFSIZE, msg_type, IPC_NOWAIT);
- if( cnt == -1 )
- { return( RET_TIMEOUT );
- }
- else
- break;
- }
-
- if( command == 0 )
- { /* get command and pid */
- if( pid)
- *pid = Msg.mtype & 0x00ffffff;
- if( ret_cmd )
- *ret_cmd = (Msg.mtype & 0xff000000) >> 24;
- }
-
- cmd = *((short *) Msg.mtext );
-
- flag = *((short *) (Msg.mtext + 2) );
- *server = *((int *) (Msg.mtext + 4) );
- *ret_id = *((int *) (Msg.mtext + 8) );
-
- if( r_flag )
- *r_flag = flag;
-
- /* printf("cmd: %hd, flag %hx, server-id: %ld\n", cmd, flag, server_id ); */
-
-
- p1 = NULL;
- p2 = NULL;
- p3 = NULL;
- p4 = NULL;
-
- switch(cmd)
- { case RET_FILE:
- case RET_ERROR:
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- if( flag & 0x01 )
- /* module given */
- p2 = strtok( NULL, "," );
- break;
-
- case RET_FUNCT:
- case RET_VAR:
- case RET_L_VAR:
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- if( !(flag & 0x01) )
- { /* position is given
- */
- p2 = strtok( NULL, "," );
- p3 = strtok( NULL, "," );
- if( !(flag & 0x02) )
- /* module given */
- p4 = strtok( NULL, "," );
- }
- break;
-
- case RET_STRUCT:
- case RET_UNION:
- case RET_ENUM:
- case RET_TYPEDEF:
- case RET_MACRO:
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- if( !(flag & 0x01) )
- { /* position is given
- */
- p2 = strtok( NULL, "," );
- p3 = strtok( NULL, "," );
- /* module ignored */
- }
- break;
-
- case RET_POS:
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- p2 = strtok( NULL, "," );
- if( flag & 0x01 )
- { /* module is given
- */
- p3 = strtok( NULL, "," );
- }
- break;
-
- case RET_REFERENCE:
- case RET_ENUM_C:
- case RET_COMP:
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- p2 = strtok( NULL, "," );
- p3 = strtok( NULL, "," );
- break;
-
- case RET_CONNECT: /* should also send a version-string to client */
- /* currently not implemented */
- case RET_REFUSED:
- case RET_DIR: /* working directory - just 1 argument */
- p1 = strtok( Msg.mtext + ARGUMENT_OFFSET, "," );
- break;
-
- case RET_END:
- case RET_OK:
- case RET_CMD_UNKNOWN:
- case RET_PLEASE_WAIT: /* currently not implemented */
- break;
-
- default:
- return( cmd ); /* unknown command */
- break;
- }
-
- arg1[0] = 0;
- arg2[0] = 0;
- arg3[0] = 0;
- arg4[0] = 0;
-
- if( p1 )
- { if( strlen( p1 ) > STRINGSIZE )
- { strncpy( arg1, p1, STRINGSIZE-1 );
- arg1[STRINGSIZE-1] = 0;
- }
- else
- strcpy( arg1, p1 );
- }
- else
- strcpy( arg1, "" );
-
- if( p2 )
- { if( strlen( p2 ) > STRINGSIZE )
- { strncpy( arg2, p2, STRINGSIZE-1 );
- arg2[STRINGSIZE-1] = 0;
- }
- else
- strcpy( arg2, p2 );
- }
- else
- strcpy( arg2, "" );
-
- if( p3 )
- { if( strlen( p3 ) > STRINGSIZE )
- { strncpy( arg3, p3, STRINGSIZE-1 );
- arg3[STRINGSIZE-1] = 0;
- }
- else
- strcpy( arg3, p3 );
- }
- else
- strcpy( arg3, "" );
-
- if( p4 )
- { if( strlen( p4 ) > STRINGSIZE )
- { strncpy( arg4, p4, STRINGSIZE-1 );
- arg2[STRINGSIZE-1] = 0;
- }
- else
- strcpy( arg4, p4 );
- }
- else
- strcpy( arg4, "" );
-
- return( cmd );
- }
-
-
- #endif /* CLIENT */
-
-